﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright company="Microsoft Corp." file="CompositeOperationBase.cs">
//   All rights reserved. See License.txt in the project root for license information.
// </copyright>
// 
// --------------------------------------------------------------------------------------------------------------------
namespace CloudBlitz.DeploymentManager.DeploymentWorkflow
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    public abstract class CompositeOperationBase : DeploymentOperationBase
    {
        private readonly object lockObject = new object();

        protected readonly IList<IDeploymentOperation> operations = new List<IDeploymentOperation>();

        private readonly IDictionary<IDeploymentOperation, double> progress = new Dictionary<IDeploymentOperation, double>();

        protected CompositeOperationBase(IEnumerable<IDeploymentOperation> operations)
        {
            var deploymentOperations = operations as IList<IDeploymentOperation> ?? operations.ToList();
            if (operations == null || !deploymentOperations.Any())
            {
                throw new ArgumentException("Collection of operations must not be null or empty");
            }

            this.operations = deploymentOperations;

            foreach (var operation in this.operations)
            {
                this.progress[operation] = 0;
                operation.ProgressChanged += this.OperationProgressChanged;
            }
        }

        public override int ProgressWeight
        {
            get
            {
                return this.operations.Sum(x => x.ProgressWeight);
            }

            protected set
            {
            }
        }

        private void OperationProgressChanged(object sender, ProgressChangedEventArgs args)
        {
            lock (this.lockObject)
            {
                var operation = sender as IDeploymentOperation;

                this.progress[operation] = ((double)args.Progress / 100) * operation.ProgressWeight;

                this.RaiseProgressChangedEvent(Convert.ToInt32((this.progress.Sum(x => x.Value) * 100) / this.ProgressWeight), args.Message);
            }
        }
    }
}